////////////////////////////////////////////////////////////////////////////////
/// @file    main.c
/// @author  AE TEAM
/// @brief   THIS FILE PROVIDES ALL THE SYSTEM FUNCTIONS.
////////////////////////////////////////////////////////////////////////////////
/// @attention
///
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
///
/// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
////////////////////////////////////////////////////////////////////////////////

// Define to prevent recursive inclusion
#define _MAIN_C_

// Files includes
#include "main.h"
#include <lwip/opt.h>
#include <lwip/arch.h>
#include "tcpip.h"
#include "reg_rcc.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "ethernetif.h"
#include "netif/ethernet.h"
#include "lwip/def.h"
#include "lwip/stats.h"
#include "lwip/etharp.h"
#include "lwip/ip.h"
#include "lwip/snmp.h"
#include "lwip/timeouts.h"
//#include "tcpclient.h"
#include "delay.h"
#include "eth_bsp_config.h"


#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "dhcp.h"

static TaskHandle_t AppTaskCreate_Handle = NULL; // Create task handle
static TaskHandle_t Test1_Task_Handle = NULL; // LED task handle
static TaskHandle_t Test2_Task_Handle = NULL; // KEY task handle


static void AppTaskCreate(void); // Used to create tasks

static void Test1_Task(void* pvParameters); // Test1_Task task implementation
static void Test2_Task(void* pvParameters); // Test2_Task task implementation

extern void TCPIP_Init(void);


extern void xPortSysTickHandler(void);
void SysTick_Handler(void)
{
    uint32_t ulReturn;
    // Enter the critical section, the critical section can be nested
    ulReturn = taskENTER_CRITICAL_FROM_ISR();

    //HAL_IncTick();
#if (INCLUDE_xTaskGetSchedulerState  == 1 )
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
#endif  /* INCLUDE_xTaskGetSchedulerState */
        xPortSysTickHandler();
#if (INCLUDE_xTaskGetSchedulerState  == 1 )
    }
#endif  /* INCLUDE_xTaskGetSchedulerState */

    // Exit the critical section
    taskEXIT_CRITICAL_FROM_ISR( ulReturn );
}

extern xSemaphoreHandle s_xSemaphore;
void ETH_RxCpltCallback(void)
{
    //LED2_TOGGLE;
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void ETH_IRQHandler()
{
    uint32_t ulReturn;
    // Enter the critical section, the critical section can be nested
    ulReturn = taskENTER_CRITICAL_FROM_ISR();

    if (ETH_GetDMAITStatus(ETH_DMA_IT_R)) {                         /* Frame received */

        ETH_RxCpltCallback();

        ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
    }
    else if (ETH_GetDMAITStatus(ETH_DMA_IT_T)) {                    /* Frame transmitted */
        /* Transfer complete callback */
        // callback

        /* Clear the Eth DMA Tx IT pending bits */
        ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
    }

    /* Clear the interrupt flags */
    ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);

    /* ETH DMA Error */
    if(ETH_GetDMAITStatus(ETH_DMA_FLAG_AIS)) {
        /* Ethernet Error callback */
        // callback

        /* Clear the interrupt flags */
        ETH_DMAClearITPendingBit(ETH_DMA_FLAG_AIS);
    }

    taskEXIT_CRITICAL_FROM_ISR( ulReturn );
}

////////////////////////////////////////////////////////////////////////////////
/// @brief   AppTaskCreate
/// @note   Contains all task creation functions
/// @param    None
/// @retval   None
////////////////////////////////////////////////////////////////////////////////
static void AppTaskCreate(void)
{
    BaseType_t xReturn = pdPASS;// Define a creation information return value, the default is pdPASS

    TCPIP_Init();

    dhcp_netconn_init();

    // Create Test1_Task task
    xReturn = xTaskCreate((TaskFunction_t )Test1_Task,  // Task entry function
                          (const char*    )"Test1_Task", // Task name
                          (uint16_t       )512,    // Task stack size
                          (void*          )NULL,   // Task entry function parameters
                          (UBaseType_t    )1,      // The priority of the task
                          (TaskHandle_t*  )&Test1_Task_Handle); // Task control block pointer
    if(pdPASS == xReturn)
        printf("Create Test1_Task sucess...\r\n");


    xReturn = xTaskCreate((TaskFunction_t )Test2_Task,   // Task entry function
                          (const char*    )"Test2_Task", // Task name
                          (uint16_t       )512,   // Task stack size
                          (void*          )NULL, // Task entry function parameters
                          (UBaseType_t    )2,  // The priority of the task
                          (TaskHandle_t*  )&Test2_Task_Handle); // Task control block pointer
    if(pdPASS == xReturn)
        printf("Create Test2_Task sucess...\n\n");

    vTaskDelete(AppTaskCreate_Handle); //Delete AppTask Create task

    taskEXIT_CRITICAL();            //Exit the critical section
}

////////////////////////////////////////////////////////////////////////////////
/// @brief   Test1_Task
/// @note   Test1_Task task body
/// @param
/// @retval   None
////////////////////////////////////////////////////////////////////////////////
static void Test1_Task(void* parameter)
{
    while (1) {
        // LED1_TOGGLE;
//    PRINT_DEBUG("LED1_TOGGLE\n");
        vTaskDelay(1000); // Delay 1000 ticks
    }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief   Test2_Task
/// @note    Test2_Task task body
/// @param
/// @retval   None
////////////////////////////////////////////////////////////////////////////////
static void Test2_Task(void* parameter)
{
    while (1) {
        //LED2_TOGGLE;
//    PRINT_DEBUG("LED2_TOGGLE\n");
        vTaskDelay(2000); //delay 2000 ticks
    }
}
int main(void)
{
    SystemTick_Count = 0;

    CONSOLE_Init(115200);

    BaseType_t xReturn = pdPASS;// Define a creation information return value, the default is pdPASS


    xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,   // Task entry function
                          (const char*    )"AppTaskCreate", // Task name
                          (uint16_t       )512,   // Task stack size
                          (void*          )NULL, // Task entry function parameters
                          (UBaseType_t    )1,  // The priority of the task
                          (TaskHandle_t*  )&AppTaskCreate_Handle); // Task control block pointer
    // Start task scheduling
    if(pdPASS == xReturn)
        vTaskStartScheduler();
    else
        return -1;

    while(1);    // Normally will not execute here

}



/// @}

/// @}

/// @}
